package com.dingwen.treasure.business.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.dingwen.treasure.base.constant.PayConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

/**
 * pay 抽象类实现
 *
 * @author dingwen
 * @date 2022/04/26
 */
@Slf4j
public abstract class AbstractPayService {


    /**
     * 执行: 除了已经捕获的异常的情况则回滚
     *
     * @return {@link Boolean}
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean execute() {

        // 1. 执行请求
        String resultStr;

        try {
            resultStr = invokeRequest();
        } catch (Exception e) {
            log.error("执行请求,出现异常，错误信息：{}", e.getMessage());
            return false;
        }


        // 2. 返回结果检查
        if (StrUtil.isBlank(resultStr) || !JSONUtil.isTypeJSON(resultStr)) {
            log.info("执行请求，返回结果为空或不是Json，返回内容：\n{}", resultStr);
            return false;
        }

        // 3. 获取返回Code
        JSONObject resultJsonObject = JSONUtil.parseObj(resultStr);

        // 获取返回结果Code
        String code = String.valueOf(resultJsonObject.get(getResultCodeKey()));

        if (Boolean.TRUE.equals(judgeResult(code))) {
            //4.  成功
            invokePayForSuccess(resultJsonObject);
            log.info("执行成功");

            // 6. 原始数据存库
            saveRawData(resultJsonObject);
            return true;
        } else {
            // 5. 失败
            invokePayForFail(resultJsonObject);
            log.info("执行失败");
            return false;
        }

    }


    /**
     * 调用三方请求：方法参数灵活完善 </br>
     * <p>抛出异常</p>
     *
     * @return {@link String}
     * @throws Exception 执行请求抛出的异常
     */
    protected abstract String invokeRequest() throws Exception;


    /**
     * 接口返回code判断
     *
     * @param code 结果码
     * @return {@link Boolean}
     */
    protected Boolean judgeResult(String code) {
        return getResultCodeValue().equals(code);
    }


    /**
     * 获取结果代码值
     *
     * @return {@link String}
     */
    protected String getResultCodeValue() {
        return PayConstant.DEFAULT_RESULT_CODE_VALUE;
    }

    /**
     * 获取结果代码 key
     *
     * @return {@link String}
     */
    protected String getResultCodeKey() {
        return PayConstant.DEFAULT_RESULT_CODE_KEY;
    }


    /**
     * 成功支付后执行
     *
     * @param jsonObject json对象
     */
    protected void invokePayForSuccess(JSONObject jsonObject) {
        log.info("invokePayForSuccess ...,结果: \n{}", JSONUtil.toJsonPrettyStr(jsonObject));
    }

    /**
     * 成功失败后执行
     *
     * @param jsonObject json对象
     */
    protected void invokePayForFail(JSONObject jsonObject) {
        log.info("invokePayForFail ...,结果: \n{}", JSONUtil.toJsonPrettyStr(jsonObject));
    }


    /**
     * 保存原始数据
     *
     * @param jsonObject json对象
     */
    protected void saveRawData(JSONObject jsonObject) {
        log.info("saveRawData ...,结果: \n{}", JSONUtil.toJsonPrettyStr(jsonObject));
    }

}
